home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 4287 / 4287.xpi / modules / undoCache.js
Text File  |  2009-11-04  |  6KB  |  250 lines

  1. var EXPORTED_SYMBOLS = ['undoCache'];
  2.  
  3. const MIN_CACHE_COUNT = 0;
  4. const MAX_CACHE_COUNT = 1000;
  5.  
  6. const Prefs = Components
  7.         .classes['@mozilla.org/preferences;1']
  8.         .getService(Components.interfaces.nsIPrefBranch);
  9.  
  10. const ObserverService = Components
  11.         .classes['@mozilla.org/observer-service;1']
  12.         .getService(Components.interfaces.nsIObserverService);
  13.  
  14. const FaviconService = Components
  15.         .classes['@mozilla.org/browser/favicon-service;1']
  16.         .getService(Components.interfaces.nsIFaviconService);
  17.  
  18. const PrivateBrowsing = 'nsIPrivateBrowsingService' in Components.interfaces ?
  19.         Components
  20.             .classes['@mozilla.org/privatebrowsing;1']
  21.             .getService(Components.interfaces.nsIPrivateBrowsingService) :
  22.         null ;
  23.  
  24. var undoCache = {
  25.  
  26.     _init : function()
  27.     {
  28.         ObserverService.addObserver(this, 'private-browsing', false);
  29.  
  30.         // "didShutdownSanitize" pref is turned on when "quite-application" is fired.
  31.         // "profile-change-teardown" is fired next to the "quite-application" event, so
  32.         // we should handle it.
  33.         ObserverService.addObserver(this, 'profile-change-teardown', false);
  34.  
  35.         if (Prefs.getBoolPref('splitbrowser.state.restore')) {
  36.             try {
  37.                 var entries = decodeURIComponent(escape(Prefs.getCharPref('splitbrowser.undo.state')));
  38.                 this._globalEntries = entries.split('|')
  39.                         .map(function(aEntry) {
  40.                             try {
  41.                                 aEntry = SplitBrowser.evalInSandbox('('+unescape(aEntry)+')');
  42.                             }
  43.                             catch(e) {
  44.                                 aEntry = null;
  45.                             }
  46.                             return aEntry;
  47.                         })
  48.                         .filter(function(aEntry) {
  49.                             return aEntry;
  50.                         });
  51.             }
  52.             catch(e) {
  53.                 this._globalEntries = [];
  54.             }
  55.         }
  56.  
  57.         this.entries = (PrivateBrowsing && PrivateBrowsing.privateBrowsingEnabled) ?
  58.                 this._privateEntries :
  59.                 this._globalEntries ;
  60.     },
  61.     _globalEntries  : [],
  62.     _privateEntries : [],
  63.  
  64.     get entries()
  65.     {
  66.         return this._entries;
  67.     },
  68.     set entries(aValue)
  69.     {
  70.         this._entries = aValue;
  71.         return aValue;
  72.     },
  73.     _entries : null,
  74.  
  75.     addEntry : function(aTitle, aIcon, aState)
  76.     {
  77.         this.entries.unshift({
  78.             title : aTitle,
  79.             icon  : aIcon,
  80.             state : aState,
  81.             date  : Date.now()
  82.         });
  83.         this.entries = this.entries.slice(0, this.maxCount);
  84.         this._onChange();
  85.     },
  86.  
  87.     getEntryAt : function(aIndex)
  88.     {
  89.         if (aIndex >= this.entries.length) return null;
  90.         return this.entries[aIndex];
  91.     },
  92.  
  93.     removeEntryAt : function(aIndex)
  94.     {
  95.         if (aIndex >= this.entries.length) return;
  96.         this.entries.splice(aIndex, 1);
  97.         this._onChange();
  98.     },
  99.  
  100.     get maxCount()
  101.     {
  102.         return Math.min(MAX_CACHE_COUNT, Math.max(MIN_CACHE_COUNT, Prefs.getIntPref('splitbrowser.undo.max')));
  103.     },
  104.  
  105.     saveEntries : function(aForce)
  106.     {
  107.         if (
  108.             (this._entries == this._privateEntries) ||
  109.             (!aForce && !Prefs.getBoolPref('splitbrowser.state.restore'))
  110.             )
  111.             return;
  112.         var entries = this.entries
  113.                 .map(function(aEntry) {
  114.                     try {
  115.                         return escape(aEntry.toSource())
  116.                     }
  117.                     catch(e) {
  118.                         return null;
  119.                     }
  120.                 })
  121.                 .filter(function(aEntry) {
  122.                     return aEntry;
  123.                 })
  124.                 .join('|');
  125.         try {
  126.             Prefs.setCharPref('splitbrowser.undo.state', unescape(encodeURIComponent(entries)));
  127.         }
  128.         catch(e) {
  129.         }
  130.     },
  131.  
  132.     clearEntries : function(aClearRange)
  133.     {
  134.         if (!aClearRange) {
  135.             this.entries = [];
  136.         }
  137.         else if (aClearRange.length == 2) {
  138.             this.entries = this.entries.filter(function(aEntry) {
  139.                 var date = aEntry.date * 1000;
  140.                 return aRange[0] <= date && aRange[1] >= date;
  141.             });
  142.         }
  143.         this._onChange();
  144.     },
  145.  
  146.     _autoSanitizeOnShutdown : function()
  147.     {
  148.         if (
  149.             Prefs.getBoolPref('privacy.sanitize.promptOnSanitize') ||
  150.             !Prefs.getBoolPref('privacy.sanitize.sanitizeOnShutdown') ||
  151.             !Prefs.prefHasUserValue('privacy.sanitize.didShutdownSanitize') ||
  152.             !Prefs.getBoolPref('privacy.sanitize.didShutdownSanitize')
  153.             )
  154.             return;
  155.         this.observe(null, 'private-browsing', 'exit');
  156.         this.clearEntries();
  157.     },
  158.  
  159.  
  160.     _broadcasters : [],
  161.  
  162.     registerBroadcaster : function(aBroadcaster)
  163.     {
  164.         if (this._broadcasters.indexOf(aBroadcaster) < 0) {
  165.             this._broadcasters.push(aBroadcaster);
  166.             this._onChange();
  167.         }
  168.     },
  169.  
  170.     unregisterBroadcaster : function(aBroadcaster)
  171.     {
  172.         var index = this._broadcasters.indexOf(aBroadcaster);
  173.         if (index > -1)
  174.             this._broadcasters.splice(index, 1);
  175.     },
  176.  
  177.     _onChange : function()
  178.     {
  179.         this._broadcasters.forEach(
  180.             this.entries.length ?
  181.                 function(aBroadcaster) {
  182.                     aBroadcaster.removeAttribute('disabled');
  183.                 } :
  184.                 function(aBroadcaster) {
  185.                     aBroadcaster.setAttribute('disabled', true);
  186.                 }
  187.         );
  188.         this.saveEntries();
  189.     },
  190.  
  191.  
  192.     initUndoList : function(aPopup)
  193.     {
  194.         var d = aPopup.ownerDocument;
  195.         var range = d.createRange();
  196.         range.selectNodeContents(aPopup);
  197.         range.deleteContents();
  198.  
  199.         var f = d.createDocumentFragment();
  200.         var max = 36;
  201.         this.entries.forEach(function(aEntry, aIndex) {
  202.             let item = f.appendChild(d.createElement('menuitem'));
  203.             item.setAttribute('label', aEntry.title);
  204.             item.setAttribute('index', aIndex);
  205.             item.setAttribute('class', 'menuitem-iconic');
  206.             item.setAttribute(
  207.                 'src',
  208.                 aEntry.icon ?
  209.                     'moz-anno:favicon:'+aEntry.icon :
  210.                     FaviconService.defaultFavicon.spec
  211.             );
  212.             if (aIndex <= max)
  213.                 item.setAttribute('accesskey', aIndex.toString(max));
  214.         }, this);
  215.  
  216.         range.insertNode(f);
  217.         range.detach();
  218.     },
  219.  
  220.     observe : function(aSubject, aTopic, aData) 
  221.     {
  222.         switch (aTopic)
  223.         {
  224.             case 'private-browsing':
  225.                 switch (aData)
  226.                 {
  227.                     case 'enter':
  228.                         if (this.entries == this._globalEntries)
  229.                             this.saveEntries();
  230.                         this._privateEntries = [];
  231.                         this.entries = this._privateEntries;
  232.                         break;
  233.                     case 'exit':
  234.                         this._privateEntries = [];
  235.                         this.entries = this._globalEntries;
  236.                         break;
  237.                 }
  238.                 this._onChange();
  239.                 return;
  240.  
  241.             case 'profile-change-teardown':
  242.                 this._autoSanitizeOnShutdown();
  243.                 return;
  244.         }
  245.     }
  246.  
  247. };
  248.  
  249. undoCache._init();
  250.